package com.ruoyi.business.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.ruoyi.business.domain.HistoricActivity;
import com.ruoyi.business.domain.ServiceItem;
import com.ruoyi.business.service.IDefinitionNodeService;
import com.ruoyi.business.service.IProcessService;
import com.ruoyi.business.service.IServiceItemService;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.page.PageDomain;
import com.ruoyi.common.core.page.TableSupport;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.mapper.SysUserMapper;
import com.ruoyi.system.service.ISysUserService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.business.mapper.CarPackageAuditMapper;
import com.ruoyi.business.domain.CarPackageAudit;
import com.ruoyi.business.service.ICarPackageAuditService;
import com.ruoyi.common.core.text.Convert;
import org.springframework.transaction.annotation.Transactional;

/**
 * 审核列Service业务层处理
 *
 * @author wolfcode
 * @date 2021-07-20
 */
@Service
public class CarPackageAuditServiceImpl implements ICarPackageAuditService {

    @Autowired
    private CarPackageAuditMapper carPackageAuditMapper;
    @Autowired
    private IProcessService processService;
    @Autowired
    private IServiceItemService serviceItemService;
    @Autowired
    private IDefinitionNodeService definitionNodeService;
    @Autowired
    private SysUserMapper sysUserMapper;

    /**
     * 查询审核列
     *
     * @param id 审核列ID
     * @return 审核列
     */
    @Override
    public CarPackageAudit selectCarPackageAuditById(Long id) {
        return carPackageAuditMapper.selectCarPackageAuditById(id);
    }

    /**
     * 查询审核列列表
     *
     * @param carPackageAudit 审核列
     * @return 审核列
     */
    @Override
    public List<CarPackageAudit> selectCarPackageAuditList(CarPackageAudit carPackageAudit) {
        carPackageAudit.setCreateBy(ShiroUtils.getUserId().toString());
        List<CarPackageAudit> carMaintenanceInfos =
                carPackageAuditMapper.selectCarPackageAuditList(carPackageAudit);
        //查询任务
        Task task = null;
        for (CarPackageAudit audit : carMaintenanceInfos) {
            //反射
            audit.setServiceItem(JSON.parseObject(audit.getServiceItemInfo(), ServiceItem.class));
            task = processService.getTaskByProcessInstanceId(audit.getInstanceId());
            if (task != null) {
                audit.setTaskId(task.getId());
                audit.setTaskName(task.getName());
            } else {
                //task==null 说明任务结束了
                audit.setTaskName("已结束");
            }
        }
        return carMaintenanceInfos;
    }

    /**
     * 新增审核列
     *
     * @param carPackageAudit 审核列
     * @return 结果
     */
    @Override
    public int insertCarPackageAudit(CarPackageAudit carPackageAudit) {
        carPackageAudit.setCreateTime(DateUtils.getNowDate());
        return carPackageAuditMapper.insertCarPackageAudit(carPackageAudit);
    }

    /**
     * 修改审核列
     *
     * @param carPackageAudit 审核列
     * @return 结果
     */
    @Override
    public int updateCarPackageAudit(CarPackageAudit carPackageAudit) {
        return carPackageAuditMapper.updateCarPackageAudit(carPackageAudit);
    }

    /**
     * 删除审核列对象
     *
     * @param ids 需要删除的数据ID
     * @return 结果
     */
    @Override
    public int deleteCarPackageAuditByIds(String ids) {
        return carPackageAuditMapper.deleteCarPackageAuditByIds(Convert.toStrArray(ids));
    }

    /**
     * 删除审核列信息
     *
     * @param id 审核列ID
     * @return 结果
     */
    @Override
    public int deleteCarPackageAuditById(Long id) {
        return carPackageAuditMapper.deleteCarPackageAuditById(id);
    }

    @Override
    public CarPackageAudit getCarPackageAudit(String id) {
        return carPackageAuditMapper.getCarPackageAudit(id);
    }

    @Override
    @Transactional
    public void cancelApply(String instanceId) {
        //把快照表的信息 状态修改为撤销 审核人设置为空
        ProcessInstance instance = processService.getProcessInstanceById(instanceId);
        //通过流程实例获取业务
        String businessKey = instance.getBusinessKey();
        //根据业务key查询审核对象，更新状态为撤销状态
        CarPackageAudit audit = carPackageAuditMapper.getCarPackageAudit(businessKey);
        audit.setStatus(CarPackageAudit.STATUS_CANCEL);
        audit.setAuditors("");
        carPackageAuditMapper.updateCarPackageAudit(audit);
        //获取服务项，更新审核状态为初始化
        ServiceItem serviceItem = JSON.parseObject(audit.getServiceItemInfo(), ServiceItem.class);
        serviceItem.setAuditStatus(ServiceItem.AUDITSTATUS_INIT);
        serviceItemService.updateServiceItemNoCondition(serviceItem);
        //执行此方法后未审批的任务 act_ru_task 会被删除，
        //流程历史 act_hi_taskinst 不会被删除，并且流程历史的状态为finished完成
        //删除流程实例
        processService.deleteProcessInstance(instanceId, "用户撤销");
    }

    //我的待办
    @Override
    public List<CarPackageAudit> findTodoList(CarPackageAudit carPackageAudit) {
        //查询当前登录用户关于汽车审核所有的待办任务总数
        long count = processService
                .selectTodoTaskCount(CarPackageAudit.DEFINITION_KEY, ShiroUtils.getUserId().toString());
        if (count > 0) {
            PageDomain pageDomain = TableSupport.buildPageRequest();
            Integer pageNum = pageDomain.getPageNum();
            Integer pageSize = pageDomain.getPageSize();
            //查询当前登录用户关于汽车审核所有的待办任务集合 分页
            List<Task> taskList = processService.selectTodoTaskList(CarPackageAudit.DEFINITION_KEY,
                    ShiroUtils.getUserId().toString(), (pageNum - 1) * pageSize, pageSize);
            //遍历待办任务,查询对应的CarPackAgeAudit
            List<CarPackageAudit> resultList = new ArrayList<>();
            CarPackageAudit audit;
            for (Task task : taskList) {
                ProcessInstance processInstance =
                        processService.getProcessInstanceById(task.getProcessInstanceId());
                String businessKey = processInstance.getBusinessKey();
                audit = carPackageAuditMapper.getCarPackageAudit(businessKey);
                audit.setServiceItem(JSON.parseObject(audit.getServiceItemInfo(), ServiceItem.class));
                audit.setTaskId(task.getId());
                audit.setTaskName(task.getName());
                resultList.add(audit);
            }
            Page<CarPackageAudit> page = new Page<>();
            page.setTotal(count);
            page.setPageNum(pageNum);
            page.setPageSize(pageSize);
            page.addAll(resultList);
            return page;
        } else {
            //如果总数为0，返回空集合
            return Collections.EMPTY_LIST;
        }
    }

    @Override
    @Transactional
    public void complete(String taskId, Boolean auditStatus, String comment) {
        //任务处理
        String commentStr = auditStatus ? "【同意】" : "【拒绝】";
        if (StringUtils.isNotEmpty(commentStr)) {
            commentStr += comment;
        }
        //根据任务id查询任务对象
        Task task = processService.getTaskByTaskId(taskId);
        ProcessInstance processInstance =
                processService.getProcessInstanceById(task.getProcessInstanceId());
        //  任务属于候选人任务,先领取.
        //  给任务添加批注信息
        //  给任务添加流程变量 流程变量的名字当前处理任务的id（任务定义key）  流程的值 auditStatus
        processService.claimAndCompleteTask(task, ShiroUtils.getUserId().toString(),
                auditStatus, commentStr);
        //查询下个任务
        //根据流程实例ID获取下一个节点. 下一个节点为空: 流程已经结束,审核通过  下一个不为空: 流程没有结束
        Task nextTask = processService.getTaskByProcessInstanceId(task.getProcessInstanceId());
        CarPackageAudit audit = carPackageAuditMapper.getCarPackageAudit(processInstance.getBusinessKey());
        //判断流程是否已经结束了.
        if (nextTask != null) {
            //下一个节点不为空: 流程节点没有结束
            List<String> auditors = new ArrayList<>();
            //如果auditStatus为true 同意
            if (auditStatus) {
                //根据下一个节点的Id在t_definition_node寻找该节点的审核人,给该节点设置候选人
                String taskDefinitionKey = nextTask.getTaskDefinitionKey();
                List<SysUser> auditorList =
                        definitionNodeService.queryByTaskDefinitionKey(taskDefinitionKey);
                for (SysUser user : auditorList) {
                    processService.addCandidateUser(nextTask, user.getUserId());
                    auditors.add(user.getUserName());
                }
            } else {
                //如果auditStatus为false 拒绝
                //        获取到该流程发起人,给当前节点设置对应的候选人为当前流程发起人
                //        t_car_package_audit状态修改成审核拒绝 1
                String userId = audit.getCreateBy();
                processService.addCandidateUser(nextTask, Long.valueOf(userId));
                auditors.add(audit.getCreateByName());
                audit.setStatus(CarPackageAudit.STATUS_REJECT);
            }
            //更新
            audit.setAuditors(JSON.toJSONString(auditors));
            carPackageAuditMapper.updateCarPackageAudit(audit);
        } else {
            //下一个节点为空: 流程已经结束 通过
            //    t_car_package_audit和t_service_item修改审核状态
            audit.setAuditors("");
            audit.setStatus(CarPackageAudit.STATUS_PASS);
            carPackageAuditMapper.updateCarPackageAudit(audit);
            //修改养修明细项审核状态
            ServiceItem serviceItem = JSON.parseObject(audit.getServiceItemInfo(), ServiceItem.class);
            serviceItem.setAuditStatus(ServiceItem.AUDITSTATUS_APPROVED);
            serviceItemService.updateServiceItemNoCondition(serviceItem);
        }

    }

    @Override
    @Transactional
    public void updateServiceItem(String carPackageAuditId, ServiceItem serviceItem) {
        serviceItemService.updateServiceItemNoCondition(serviceItem);
        CarPackageAudit audit = carPackageAuditMapper.getCarPackageAudit(carPackageAuditId);
        audit.setServiceItemInfo(JSON.toJSONString(serviceItem));
        carPackageAuditMapper.updateCarPackageAudit(audit);
    }

    //重新申请
    @Override
    @Transactional
    public void reApply(String taskId, String carPackageAuditId) {
        //根据任务id获取任务
        Task task = processService.getTaskByTaskId(taskId);
        //创建carPackageAudit对象
        CarPackageAudit audit = carPackageAuditMapper.getCarPackageAudit(carPackageAuditId);
        //获取服务项对象
        ServiceItem serviceItem = JSON.parseObject(audit.getServiceItemInfo(), ServiceItem.class);
        //重新设置折扣价流程变量
        processService.setVariable(taskId, "money", serviceItem.getDiscountPrice().longValue());
        //添加批注 领取任务 完成任务
        processService.claimAndCompleteTask(task, ShiroUtils.getUserId().toString(), true, "重新申请");
        //查询下个任务节点
        Task nextTask = processService.getTaskByProcessInstanceId(task.getProcessInstanceId());
        ProcessInstance processInstance = processService.getProcessInstanceById(task.getProcessInstanceId());
        //指定下一个任务的候选人
        String taskDefinitionKey = nextTask.getTaskDefinitionKey();
        List<String> auditors = new ArrayList<>();
        List<SysUser> auditorList = definitionNodeService.queryByTaskDefinitionKey(taskDefinitionKey);
        for (SysUser user : auditorList) {
            //给任务设置候选人
            processService.addCandidateUser(nextTask, user.getUserId());
            //把候选人名字存到集合
            auditors.add(user.getUserName());
        }
        //设置申请快照状态
        audit.setStatus(CarPackageAudit.STATUS_IN_ROGRESS);
        //设置审核人的名字 转为JSON字符串
        audit.setAuditors(JSON.toJSONString(auditors));
        //更新数据库
        carPackageAuditMapper.updateCarPackageAudit(audit);
    }

    @Override
    public List<CarPackageAudit> findDoneList(CarPackageAudit carPackageAudit) {
        //获取已办任务总数
        long count = processService
                .selectDoneTaskCount(CarPackageAudit.DEFINITION_KEY, ShiroUtils.getUserId().toString());
        if (count > 0) {
            //分页查询
            PageDomain pageDomain = TableSupport.buildPageRequest();
            Integer pageNum = pageDomain.getPageNum();
            Integer pageSize = pageDomain.getPageSize();
            //HistoricTaskInstance 只是包含用户历史任务 userTask
            //HistoricActivityInstance 包含节点
            List<HistoricTaskInstance> taskList = processService.selectDoneTaskList(CarPackageAudit.DEFINITION_KEY,
                    ShiroUtils.getUserId().toString(), (pageNum - 1) * pageSize, pageSize);
            //
            List<CarPackageAudit> resultList = new ArrayList<>();
            CarPackageAudit audit;
            for (HistoricTaskInstance task : taskList) {
                //获取历史流程实例
                HistoricProcessInstance historicProcessInstance =
                        processService.getHistoricProcessInstanceById(task.getProcessInstanceId());
                String businessKey = historicProcessInstance.getBusinessKey();
                audit = carPackageAuditMapper.getCarPackageAudit(businessKey);
                audit.setServiceItem(JSON.parseObject(audit.getServiceItemInfo(), ServiceItem.class));
                audit.setTaskId(task.getId());
                audit.setTaskName(task.getName());
                audit.setDoneTime(task.getEndTime());
                resultList.add(audit);
            }
            Page<CarPackageAudit> page = new Page<>();
            page.setTotal(count);
            page.setPageNum(pageNum);
            page.setPageSize(pageSize);
            page.addAll(resultList);
            return page;
        } else {
            return Collections.EMPTY_LIST;
        }
    }

    @Override
    public List<HistoricActivity> selectHistoryList(String instanceId) {
        //获取历史流程实例 包含起始结束节点
        //HistoricActivity类是HistoricActivityInstance接口的实现类HistoricActivityInstanceEntityImpl的子类
        List<HistoricActivityInstance> instanceList = processService.selectHistoryTaskList(instanceId);
        //创建HistoricActivity集合
        List<HistoricActivity> resultList = new ArrayList<>();
        for (HistoricActivityInstance instance : instanceList) {
            HistoricActivity historicActivity = new HistoricActivity();
            //拷贝属性
            BeanUtils.copyProperties(instance, historicActivity);
            //查询批注并设置
            String comment = processService.getTaskComment(instance.getTaskId());
            historicActivity.setComment(comment);
            //获取任务处理人的id
            String assignee = instance.getAssignee();
            if (StringUtils.isNotEmpty(assignee)) {
                SysUser user = sysUserMapper.selectUserById(Long.parseLong(assignee));
                if (user != null) {
                    historicActivity.setAssigneeName(user.getUserName());
                }
            }
            resultList.add(historicActivity);
        }
        return resultList;
    }
}
